Published 2006-02-18 10:56:21

It's either Continuing Professional Development, or just getting so bored that learning something new is the only cure. But I finally sat down this week a dug into D.

D, for the uninformed, is billed by it's author as a successor to C++, (and to some respect C). The website is a little tricky to understand (the 4 links on the left are the key navigation - Language = Overview of language, and Phebos = core library docs). The Documentation is clear, and reasonably well expressed with quite a few examples. (although it could probably do with PHP's comment system.)

There is also a PEAR/CPAN style site, dsource.org, which has a few projects written in D. including wrappers around common C libraries (which make them more OO like - even though you can directly access C calls in the language without wrappers.).

What makes this language interesting is quite a few key points
  • It compiles into .exe/binary/.so/.dll etc.
  • The core library is tiny ~1Mb (500K striped) compared with the classic java/C# frameworks
  • memory management (autofreeing at the end of each function) - so you dont need to splatter the code with malloc()(/free()
    [slight correction thanks to Regan Heath] - this is really due to the built in garbage collector, and the auto free'ing only occurs when you define the type as auto, or when resources get tight.
  • The core library is small and limited (so I dont have to learn 1000's of classes/packages to understand code)..
  • The code syntax is similar to PHP/Java/C# etc. for class construction / definition,
  • native Arrays and Associative Array's, just like PHP!.
  • No need for .h header files
  • It's pretty damn fast! - beat's gcc in benchmarks (well even considering you always take them with a pinch of salt)
  • It just works....
A simple D Code... (It's LGPL'ed from the DUI distribution)
/* See original for copyright - I've removed for the example) */

// give this file a module name (bit like namespaces)
module hw.HelloWorld;

// private imports so that any code importing this,
// doesnt import these as well.
// so you dont flood the global namespace too much..
private import dui.MainWindow;
private import dui.DUI;

public:
class HelloWorld : MainWindow // it extends MainWindow..
{
private import dui.Label; // imports can go here as well..

char[char[]] testarray = [ // yah - native array's in prop. def's
"one": "1",
"two": "2"
]; // oops - this doesnt work (although it may do in the future)
// thanks to Jarrett Billingsley for spotting this..

char[][] testarray = [
// well, semi-yah limited support
1: "atest",
// for assoc. array initalizers..
5: "another test",
];


this() // yeap that's the constructor..
{
super("DUI Hello World"); // like parent::_construct()
this.setBorderWidth(10); // you dont need this. , but
// I think it add's clarity.

this.add(new Label("Hello World" ~ testarray["one"]));
// string concat with the ~
// operator.
this.show();
}
}

void main(char[][] args)
{
DUI dui = DUI.dui(args); // pass parameters to Gtk+
new HelloWorld();
dui.go(); // start the main event loop
}

Click on the more bit for the full story..
Well, as you've guessed, so far I've not hit any big roadblocks, having downloaded the d compiler dmd, hello.d compiled and ran after editing a one line config file /etc/dmd.conf, even that is not really needed...
int main(char[][] args)
{
printf("Hello World\n");
printf("args.length = %d\n", args.length);
for (int i = 0; i < args.length; i++) {
printf("args[%d] = '%s'\n",
i,
cast(char *)args[i]);
}
return 0;
}
and can be compiled with the simple line:
#dmd -I/dmd/src/phobos hello.d

[suggested improvement from Jarret Billingsley] - which makes use of foreach and writefln, rather good ole printf()

int main(char[][] args)
{
writefln("Hello World");
writefln("args.length = ", args.length);
foreach (uint i, char[] arg, args) {
writefln("args[",i,'] = '%s'", arg);
}
return 0;
}



The compiler works pretty much the same way gcc does, using -lpthread (for linking in lib's), and -I for include paths.

After getting this far, without challenging myself too much, I decided to push things a bit, and look for a gui. It looks like the two most complete ones are probably Win32 Native bindings, and GTK (called DUI for some reason?)
You can find all of them on dsource.org.
The Gtk bindings pretty much compile as checked out from subversion, and the errors that do come up, are pretty obvious and easy to fix (eg. src/dui/Label.d has to be changed like this:
@@ -231,7 +231,7 @@
GtkWidget *gtkO= gtk_label_get_mnemonic_widget(gtkW());
if ( gtkO is null )
{
- null;
+ return null;
}
return new Widget(gtkO);
}

The compiler error was pretty obvious, what was wrong, what line/file etc.

To actually make it build involves building one other library, dool (also on dsource.org), and modifying the makefile.DUI to suite your enviroment, for me this meant these simple changes.

@@ -19,8 +19,8 @@
##########################
COMP_dui = dmd
COMP_FLAGS_dui = -c -g -O -od../obj -op
-COMP_IMPORT_dui = -I/home/ruimt/devel/D1/Dool/src:
/home/ruimt/dmd/src/phobos/:/home/ruimt/dmd/src/phobos
-LINK_LIBS_dui=-lphobos -lpthread -L/home/ruimt/devel/D1/Dool -ldool
+COMP_IMPORT_dui = -I/usr/src/dool/src:/dmd/src/phobos/:/dmd/src/phobos
+LINK_LIBS_dui=-lphobos -lpthread -L/usr/src/dool -ldool
LINK_dui=ar rcs
I have a suspicion that the author doesnt manually edit the Makefiles and autogenerates the from his editor, as hardcoding locations is not really the best of ideas. Anyway after those small changes, he presto, the gtk demo, and hello world on gtk work!

Aparently this also works ok on Win32..

So I got Gtk's test application up and going, and still no big hastles...

Next what to do with this new toy.. Considering that Last time I got to this stage with PHP-Gtk, I ended up writing an editor, I was not that suprised that the author of the Gtk bindings had also written and editor based around the Scintilla widget.

Getting this working was a little more complex, more due to the fact that scintilla
doesnt build as a shared library by default.

This is the Makefile patch I ended up using, still a bit messy, and based of quite a bit of googling.

** DIFF SLIGHTLY BROKEN AS I'VE HAD TO WRAP IT TO FIT ON THE PAGE...
@@ -7,7 +7,7 @@
# To force GTK+ 2 build, define GTK2 on the make command line.
# To force GTK+ 1 build, define GTK1 on the make command line.

-.SUFFIXES: .cxx .c .o .h .a
+.SUFFIXES: .cxx .c .o .h .a .so
CC = g++
CCOMP = gcc
AR = ar
@@ -17,14 +17,15 @@
RANLIB = ranlib
endif

-COMPLIB=../bin/scintilla.a
+COMPLIB=../bin/libscintilla.a
+SHAREDLIB=../bin/libscintilla.so
+

vpath %.h ../src ../include
vpath %.cxx ../src

INCLUDEDIRS=-I ../include -I ../src
-CXXBASEFLAGS=-Wall -Wno-missing-braces
-Wno-char-subscripts -DGTK -DSCI_LEXER $(INCLUDEDIRS)
-
+CXXBASEFLAGS=-Wall -Wno-missing-braces
-Wno-char-subscripts -DGTK -DSCI_LEXER $(INCLUDEDIRS) -Dunix
ifdef NOTHREADS
THREADFLAGS=-DG_THREADS_IMPL_NONE
else
@@ -34,20 +35,20 @@
ifdef DEBUG
CXXFLAGS=-DDEBUG -g $(CXXBASEFLAGS) $(THREADFLAGS)
else
-CXXFLAGS=-DNDEBUG -Os $(CXXBASEFLAGS) $(THREADFLAGS)
+CXXFLAGS+=-DNDEBUG $(CXXBASEFLAGS) $(THREADFLAGS)
endif

# If explicit setting of GTK1 or GTK2 then use that else look for
# pkg-config which is an OK indication that GTK2 is available
ifdef GTK2
-CONFIGFLAGS=pkg-config --cflags gtk+-2.0
+CONFIGFLAGS=pkg-config --cflags gtk+-2.0 gthread-2.0 glib-2.0
MARSHALLER=scintilla-marshal.o
else
ifdef GTK1
CONFIGFLAGS=gtk-config --cflags
else
ifneq (,$(findstring /,$(shell whereis pkg-config)))
-CONFIGFLAGS=pkg-config --cflags gtk+-2.0
+CONFIGFLAGS=pkg-config --cflags gtk+-2.0 gthread-2.0 glib-2.0
MARSHALLER=scintilla-marshal.o
else
CONFIGFLAGS=gtk-config --cflags
@@ -56,7 +57,11 @@
endif

.cxx.o:
- $(CC) `$(CONFIGFLAGS)` $(CXXFLAGS) -c $<
+ $(CXX) `$(CONFIGFLAGS)` $(CXXFLAGS) -c $<
+.cxx.so:
+ $(CXX) -fPIC `$(CONFIGFLAGS)` $(CXXFLAGS) -o $@ -c $<
+
+
.c.o:
$(CCOMP) `$(CONFIGFLAGS)` $(CXXFLAGS) -w -c $<

@@ -70,24 +75,41 @@
LexLout.o LexLua.o LexMatlab.o LexMetapost.o LexMMIXAL.o LexMPT.o LexMSSQL.o \
LexNsis.o LexOthers.o LexPascal.o LexPB.o LexPerl.o LexPOV.o LexPS.o \
LexPython.o LexRebol.o LexRuby.o LexScriptol.o LexSmalltalk.o LexSpecman.o \
-LexSQL.o LexTADS3.o LexTeX.o LexVB.o LexVerilog.o LexVHDL.o LexYAML.o
+LexSQL.o LexTADS3.o LexTeX.o LexVB.o LexVerilog.o LexVHDL.o LexYAML.o
#--Autogenerated -- end of automatically generated section

-all: $(COMPLIB)
+all: static shared
+
+static: $(COMPLIB)
+shared: $(SHAREDLIB)
+
+install: install-shared
+ mkdir -p ${PREFIX}/include/scintilla
+ install -m 444 ../include/*.h ${PREFIX}/include/scintilla
+ install -m 444 ${COMPLIB} ${PREFIX}/lib
+
+install-shared:
+ install -m 444 ${SHAREDLIB} ${PREFIX}/lib

clean:
rm -f *.o $(COMPLIB)

deps:
- $(CC) -MM `$(CONFIGFLAGS)` $(CXXFLAGS) *.cxx ../src/*.cxx >deps.mak
+ $(CXX) -MM `$(CONFIGFLAGS)` $(CXXFLAGS) *.cxx ../src/*.cxx >deps.mak

-$(COMPLIB): DocumentAccessor.o WindowAccessor.o
KeyWords.o StyleContext.o Document.o CallTip.o \
+LIBOBJS = DocumentAccessor.o WindowAccessor.o
KeyWords.o StyleContext.o Document.o CallTip.o \
ScintillaBase.o ContractionState.o Editor.o
ExternalLexer.o PropSet.o PlatGTK.o \
KeyMap.o LineMarker.o ScintillaGTK.o CellBuffer.o ViewStyle.o \
- RESearch.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o \
- $(MARSHALLER) $(LEXOBJS)
+ RESearch.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o
$(LEXOBJS)
+
+$(COMPLIB): $(LIBOBJS)
$(AR) rc $@ $^
$(RANLIB) $@

+$(SHAREDLIB): $(addsuffix .so,$(basename $(LIBOBJS)))
+ $(CC) -shared -fPIC -o $@ -Wl,-soname,$(notdir $(SHAREDLIB)) \
+ `pkg-config --libs gtk+-2.0 gthread-2.0 glib-2.0` $^
+
+
# Automatically generate header dependencies with "make deps"
include deps.mak





After that, only one other small modification seems to be needed to scintilla/gtk/ScintillaGTK.cxx
@@ -47,7 +47,6 @@
#include "gtk/gtkmarshal.h"
#if GTK_MAJOR_VERSION >= 2
#include "scintilla-marshal.h"
+#include "scintilla-marshal.c"
#endif

#ifdef SCI_LEXER

now running make will output a nice .so file.. - which appears to work..

The editor he had written is called leds, which again needs one or two extra libraries to build (all available on dsoure.org), Leds compiles pretty easily after modifying the Makefile to suite your enviroment.

The only small problem getting leds to work was more related to using the scintilla.so, which during the experimentation with the make file and patches above, proved difficult to test, as the Linker that leds/dui uses, currently ignores silently dl_error() messages, so I had to add a small printf to that code to see if I had built the scintilla.so correctly.

Leds editorTo try and get a better understanding of D and also curious to see how someone else had solve the same problem I had done all those years ago, I hacked a few features to leds. based on my knowledge of the lexer, I managed to add PHP syntax support, and attempted to tidy up the preference's definition code,
Having features like assert(), inside a methods pre-run area's made finding bugs alot easier..


I even found some code for a simple threaded Httpd server. that was ~ 100 lines, and worked pretty well..



The only snag I've found so far, is that googling for 'D' is not very efficient...



Mentioned By:
google.com : february (143 referals)
www.planet-php.net : Planet PHP (49 referals)
www.digitalmars.com : Two little blog/tutorials posts. (42 referals)
google.com : interesting languages (28 referals)
google.com : december (22 referals)
dstress.kuehne.cn : dstress.kuehne.cn: links (22 referals)
www.digitalmars.com : Digital Mars - digitalmars.D.learn - Two little blog/tutorials posts. (15 referals)
lists.puremagic.com : Two little blog/tutorials posts. (13 referals)
planet.debian.org.hk : Debian HK : Debian @ Hong Kong (12 referals)
images.google.com : Google Image Result for http://www.akbkhome.com/FlexyWiki/templates/images/dgtk.jpg (12 referals)
images.google.nl : Google Image Result for http://www.akbkhome.com/FlexyWiki/templates/images/leds.jpg (11 referals)
google.com : php interesting (10 referals)
2mojitos.livejournal.com : 2 mojitos (10 referals)
google.com : jarrett billingsley (8 referals)
google.com : interesting (6 referals)
images.google.pl : Wyniki Szukania w Grafice Google dla http://www.akbkhome.com/FlexyWiki/templates/images/leds.jpg (5 referals)
google.com : d compiler gtk (5 referals)
www.digitalmars.com : Re: Two little blog/tutorials posts. (4 referals)
images.google.de : Google-Ergebnis fr http://www.akbkhome.com/FlexyWiki/templates/images/leds.jpg (4 referals)
images.google.com.ar : Resultados de la Bsqueda de imgenes de Google de http://www.akbkhome.com/FlexyWiki/templates/images/leds.jpg (4 referals)

Comments

Nice Run Down
Very good article. I have a feeling that your article might end up being the top google entry for D, so I might as well bookmark it now;)
#0 - John Cox ( Link) on 2006-02-18 13:23:21 Delete Comment
DUI
Its interesting that you chose DUI for your examples. Good job giving a preview of it. Note, though, that the author, Antonio, is in the process of changing the name to DUIT and is releasing some changes to some of the base method names.

Also the Scintilla fix for the makefile should have been included in the DUI distribution; I made the original fix for that on Linux so that scintilla would compile as a shared library. A fix was also required to get a proper dll working on windows, I think. I'm not sure if these fixes were included in the actual distribution, though.

More info can be found at the project's forum:

http://www.dsource.org/forums/viewforum.php?f=45
#1 - John Reimer ( Link) on 2006-02-28 14:07:52 Delete Comment

Add Your Comment

Follow us on